package com.ruoyi.bill.service.impl;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.ruoyi.basicsystem.domain.ZnSupplier;
import com.ruoyi.basicsystem.mapper.ZnAccountItemMapper;
import com.ruoyi.basicsystem.service.IZnAccountService;
import com.ruoyi.basicsystem.service.IZnPersonService;
import com.ruoyi.basicsystem.service.IZnSupplierService;
import com.ruoyi.bill.domain.*;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.BusinessConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.RedisConstant;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtil;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.material.domain.*;
import com.ruoyi.material.mapper.ZnMaterialCurrentStockMapper;
import com.ruoyi.material.mapper.ZnMaterialMapper;
import com.ruoyi.material.mapper.ZnUnitMapper;
import com.ruoyi.material.service.IZnMaterialInitialStockService;
import com.ruoyi.system.domain.ZnCompanyConfig;
import com.ruoyi.system.domain.ZnStockCheckHistory;
import com.ruoyi.system.mapper.ZnCompanyConfigMapper;
import com.ruoyi.system.mapper.ZnProfitDetailMapper;
import com.ruoyi.system.mapper.ZnProfitHistoryMapper;
import com.ruoyi.system.mapper.ZnStockCheckHistoryMapper;
import com.ruoyi.system.service.IZnProfitDetailService;
import com.ruoyi.system.service.IZnStockCheckHistoryService;
import com.ruoyi.system.service.IZnUserBusinessService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.bill.mapper.ZnDepotHeadMapper;
import com.ruoyi.bill.service.IZnDepotHeadService;

import javax.servlet.http.HttpServletResponse;

/**
 * 单据管理Service业务层处理
 *
 * @author nexiaozi
 * @date 2022-02-19
 */
@Service
public class ZnDepotHeadServiceImpl implements IZnDepotHeadService
{
    @Autowired
    private ZnDepotHeadMapper znDepotHeadMapper;
    @Autowired
    private IZnMaterialInitialStockService znMaterialInitialStockService;
    @Autowired
    private IZnPersonService znPersonService;
    @Autowired
    private IZnAccountService znAccountService;
    @Autowired
    private ZnMaterialCurrentStockMapper znMaterialCurrentStockMapper;
    @Autowired
    private ZnMaterialMapper znMaterialMapper;
    @Autowired
    private ZnCompanyConfigMapper znCompanyConfigMapper;
    @Autowired
    private IZnUserBusinessService znUserBusinessService;
    @Autowired
    private ZnAccountItemMapper znAccountItemMapper;
    @Autowired
    private IZnSupplierService znSupplierService;

    @Autowired
    private ZnUnitMapper znUnitMapper;

    @Autowired
    private ZnProfitDetailMapper znProfitDetailMapper;

    @Autowired
    private ZnProfitHistoryMapper znProfitHistoryMapper;

    @Autowired
    private IZnProfitDetailService znProfitDetailService;

    @Autowired
    private ZnStockCheckHistoryMapper znStockCheckHistoryMapper;

    @Autowired
    private RedisCache redisCache;
    private final static String TYPE = "入库";
    private final static String SUM_TYPE = "number";
    private final static String IN = "in";
    private final static String OUT = "out";

    /**
     * 查询单据管理
     *
     * @param id 单据管理主键
     * @return 单据管理
     */
    @Override
    public ZnDepotHead selectZnDepotHeadById(Long id)
    {
        ZnDepotHead znDepotHead = znDepotHeadMapper.selectZnDepotHeadById(id);
        List<ZnDepotItem> list = znDepotHead.getZnDepotItemList();
//        Collections.sort(list, new Comparator<ZnDepotItem>() {
//            @Override
//            public int compare(ZnDepotItem o1, ZnDepotItem o2) {
//                return o1.getId().compareTo(o2.getId());
//            }
//        });
//        System.out.println(JSON.toJSONString(list));
        list.sort((x,y)->Long.compare(x.getId(), y.getId()));
//        System.out.println(JSON.toJSONString(list));
//        znDepotHead.setZnDepotItemList(list);
//        list = list.stream().sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList());
        return znDepotHead;

    }

    /**
     * 查询单据管理列表
     *
     * @param znDepotHead 单据管理
     * @return 单据管理
     */
    @Override
    @Transactional
    public List<ZnDepotHead> selectZnDepotHeadList(ZnDepotHead znDepotHead)
    {
        if(!SecurityUtils.isAdmin(SecurityUtils.getUserId())){
            znDepotHead.setTenantId(SecurityUtils.getTenantId());
            znDepotHead.setDeleteFlag("0");
            if(StringUtils.isNotBlank(znDepotHead.getMaterial())){
                znDepotHead.setMaterial(znDepotHead.getMaterial().trim());
            }
            ZnCompanyConfig znCompanyConfig= redisCache.getCacheObject(RedisConstant.SYSTEM_CONFIG+"_"+SecurityUtils.getTenantId());
            if(znCompanyConfig==null){
                znCompanyConfig = znCompanyConfigMapper.selectZnCompanyConfigBytenantId(SecurityUtils.getTenantId());
                redisCache.setCacheObject(RedisConstant.SYSTEM_CONFIG+"_"+SecurityUtils.getTenantId(),znCompanyConfig);
            }
            if(znCompanyConfig!=null){
                boolean depotFlag ="1".equals(znCompanyConfig.getDepotFlag())?true:false; //获取系统配置，是否需要用户需要分配仓库，暂时先写false
                if(depotFlag) {
                    List<String> depotIds = redisCache.getCacheList(RedisConstant.SYSTEM_CONFIG_USER_DEPOT_LIST +"_"+SecurityUtils.getTenantId());
                    List<Long> values=new ArrayList<>();
                    if(null!=depotIds&&depotIds.size()>0){
                        Map<String,Object> params = new HashMap<>();
                        params.put("depotIds",depotIds);
                        znDepotHead.setParams(params);
                    }
                }
            }
        }
        if(znDepotHead.getParams().containsKey("ids")){
            znDepotHead.getParams().put("ids",znDepotHead.getParams().get("ids").toString().split(","));
        }
            List<ZnDepotHead> list = znDepotHeadMapper.selectZnDepotHeadList(znDepotHead);
            if (list.size()>0){
                for (ZnDepotHead znDepotHead1:list) {
                    String materialNames = znDepotHeadMapper.findMaterialsListByHeaderId(znDepotHead1.getId());
                    znDepotHead1.setMaterial(materialNames);
                }
            }

//        System.out.println(JSON.toJSONString(list));
        return list;
    }

    /**
     * 新增单据管理
     *
     * @param znDepotHead 单据管理
     * @return 结果
     */
    @Transactional
    @Override
    @RepeatSubmit
    public int insertZnDepotHead(ZnDepotHead znDepotHead)
    {
        ZnDepotHead temp =  new ZnDepotHead();
        temp.setDefaultNumber(znDepotHead.getDefaultNumber());
//        temp.setTenantId(SecurityUtils.getTenantId());
//        temp.setDeleteFlag("0");
        int count = znDepotHeadMapper.selectZnDepotHeadCount(temp);
        String type = znDepotHead.getDefaultNumber().substring(0,4);
        if(count>0){
            znDepotHead.setNumber(getBillNo(type));
        }else{
            znDepotHead.setNumber(znDepotHead.getDefaultNumber());
        }
        //仓库模块的统计金额为空
        if(znDepotHead.getDiscountLastMoney() ==null){
            znDepotHead.setDiscountLastMoney(znDepotHead.getTotalPrice());
        }
//        if(znDepotHead.getChangeAmount()==null || znDepotHead.getChangeAmount().doubleValue()==0){
//            znDepotHead.setChangeAmount(znDepotHead.getDiscountLastMoney());
//        }
        if(BusinessConstants.DEPOTHEAD_TYPE_IN.equals(znDepotHead.getType())){
//            changeAmount backAmount totalPrice discountLastMoney
            znDepotHead.setChangeAmount(BigDecimal.ZERO.subtract(znDepotHead.getChangeAmount()));
            znDepotHead.setTotalPrice(BigDecimal.ZERO.subtract(znDepotHead.getTotalPrice()));
//            if(znDepotHead.getDiscountLastMoney() !=null){
//                znDepotHead.setDiscountLastMoney(BigDecimal.ZERO.subtract(znDepotHead.getDiscountLastMoney()));
//            }
        }

        Date date = DateUtils.getNowDate();
        znDepotHead.setCreateTime(date);
//        znDepotHead.setOperTime(date);
        znDepotHead.setCreator(SecurityUtils.getUserId());
        znDepotHead.setTenantId(SecurityUtils.getTenantId());
        znDepotHead.setUserId(SecurityUtils.getUserId());
        znDepotHead.setStatus("0");
//        znDepotHead.setDeptId(SecurityUtils.getDeptId());
        int rows = znDepotHeadMapper.insertZnDepotHead(znDepotHead);
        insertZnDepotItem(znDepotHead);
        if(znDepotHead.getType().equals("出库") && znDepotHead.getSubType().equals("零售") || znDepotHead.getType().equals("入库") && znDepotHead.getSubType().equals("零售退货")){
            //出库需要将金额转为负数
            if(BusinessConstants.PAY_TYPE_PREPAID.equals(znDepotHead.getPayType())){
                if(znDepotHead.getOrganId()!=null) {
                    ZnSupplier znSupplier = new ZnSupplier();
                    znSupplier.setId(znDepotHead.getOrganId());
                    Map<String,Object> params = new HashMap<>();
                    params.put("advanceIn",znDepotHead.getTotalPrice());
                    params.put("updateType","-");
                    znSupplier.setParams(params);
                    znSupplier.setType("会员");
                    znSupplierService.updateZnSupplier(znSupplier); //updateAdvanceIn(znDepotHead.getOrganId(), BigDecimal.ZERO.subtract(znDepotHead.getTotalPrice()));
                }
            }
        }
        //如何有关联订单，需要更新关联订单的状态
        if(StringUtils.isNotBlank(znDepotHead.getLinkNumber()) && (znDepotHead.getType().equals("入库") && znDepotHead.getSubType().equals("采购") || znDepotHead.getType().equals("出库") && znDepotHead.getSubType().equals("销售"))){
            ZnDepotHead updateBean  = new ZnDepotHead();
            updateBean.setNumber(znDepotHead.getLinkNumber());
            updateBean.setTenantId(znDepotHead.getTenantId());
            updateBean.setStatus("1");
            updateBean.setDeleteFlag("0");
            int updateCount =znDepotHeadMapper.updateOrderStatusByNumber(updateBean);
            if(updateCount==0){
                throw new ServiceException("更新关联订单状态异常");
            }
        }
        Set<String> usedBillNoSet = redisCache.getCacheSet(RedisConstant.USED_BILL_NO + "_"  + SecurityUtils.getTenantId() +"_" + type);
        if(usedBillNoSet ==null){
            usedBillNoSet = new HashSet<>();
        }
        usedBillNoSet.add(znDepotHead.getNumber());
        redisCache.setCacheSet(RedisConstant.USED_BILL_NO + "_"  + SecurityUtils.getTenantId() +"_" + type,usedBillNoSet);
//        //商品库存处理
//        List<Long> materialIds = new ArrayList<>();
//        for (ZnDepotItem znDepotItem:znDepotHead.getZnDepotItemList()) {
//            materialIds.add(znDepotItem.getMaterialId());
//        }
        int updateType = -1;// -1 不操作 0 减库存  1加库存
        if(znDepotHead.getType().equals("入库")){
//            if(!znDepotHead.getSubType().equals("其它")){
                updateType = 1;
//            }
        }else if(znDepotHead.getType().equals("出库")){
//            if(!znDepotHead.getSubType().equals("其它")){
                updateType = 0;
//            }
        }
        if(updateType !=-1){
//            System.out.println(JSON.toJSONString(znDepotHead.getZnDepotItemList()));
//            判断商品是否有库存，没用要新增库存 已经在新增新增商品、仓库的时候进行新增记录，该处暂时不进行判断 ，但是还是需要判断是否负库存
            for (ZnDepotItem znDepotItem:znDepotHead.getZnDepotItemList()) {
                ZnMaterialCurrentStock znMaterialCurrentStock =  new ZnMaterialCurrentStock();
                znMaterialCurrentStock.setMaterialId(znDepotItem.getMaterialId());
                znMaterialCurrentStock.setDepotId(znDepotItem.getDepotId());
                znMaterialCurrentStock.setTenantId(znDepotItem.getTenantId());
                znMaterialCurrentStock.setDeleteFlag("0");
                Integer c = znMaterialCurrentStockMapper.selectZnMaterialCurrentStockCount(znMaterialCurrentStock);
                if(c ==0){
                    znMaterialCurrentStock.setCurrentNumber(new BigDecimal(0));
                    znMaterialCurrentStockMapper.insertZnMaterialCurrentStock(znMaterialCurrentStock);
                }
            }
            Map<String,ZnDepotItem> map = new HashMap<>();
            List<ZnDepotItem> znDepotItemList = new ArrayList<>();
            Set<Long> materialIdSet = new HashSet<>();
            List<Long> materialIds = new ArrayList<>();
            for (ZnDepotItem znDepotItem:znDepotHead.getZnDepotItemList()) {
                if(materialIdSet.contains(znDepotItem.getMaterialId())){
                    ZnDepotItem ZnDepotItem_temp =  map.get(znDepotItem.getMaterialId().toString());
                    ZnDepotItem_temp.setBasicNumber(ZnDepotItem_temp.getBasicNumber().add(znDepotItem.getBasicNumber()));
                    ZnDepotItem_temp.setOperNumber(ZnDepotItem_temp.getOperNumber().add(znDepotItem.getOperNumber()));
                    map.put(znDepotItem.getMaterialId().toString(),ZnDepotItem_temp);
                }else{
                    map.put(znDepotItem.getMaterialId().toString(),znDepotItem);
                    materialIds.add(znDepotItem.getMaterialId());
                    materialIdSet.add(znDepotItem.getMaterialId());
;                }
            }
            for (Map.Entry<String,ZnDepotItem> e:map.entrySet()) {
                znDepotItemList.add(e.getValue());
            }
            znMaterialCurrentStockMapper.updateMaterialStockNum(znDepotItemList,materialIds,znDepotHead.getTenantId(),updateType);
        }
        return rows;
    }

    /**
     * 修改单据管理
     *
     * @param znDepotHead 单据管理
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateZnDepotHead(ZnDepotHead znDepotHead)
    {
        System.out.println(JSON.toJSONString(znDepotHead));
        int updateType = -1;// -1 不操作 0 减库存  1加库存
        //先将原来的商品的库存去除
        if(znDepotHead.getType().equals("入库")){
            if(!znDepotHead.getSubType().equals("其它")){
                updateType = 1;
            }
        }else if(znDepotHead.getType().equals("出库")){
            if(!znDepotHead.getSubType().equals("其它")){
                updateType = 0;
            }
        }

        if(updateType !=-1){
            ZnDepotHead znDepotHead_temp = znDepotHeadMapper.selectZnDepotHeadById(znDepotHead.getId());
            Map<String,ZnDepotItem> map = new HashMap<>();
            List<ZnDepotItem> znDepotItemList = new ArrayList<>();
            Set<Long> materialIdSet = new HashSet<>();
            List<Long> materialIds = new ArrayList<>();
            //1、有商品的出入库有商品库存变化，先进行去除
            for (ZnDepotItem znDepotItem:znDepotHead_temp.getZnDepotItemList()) {
                if(materialIdSet.contains(znDepotItem.getMaterialId())){
                    ZnDepotItem ZnDepotItem_temp =  map.get(znDepotItem.getMaterialId().toString());
                    ZnDepotItem_temp.setBasicNumber(ZnDepotItem_temp.getBasicNumber().add(znDepotItem.getBasicNumber()));
//                    ZnDepotItem_temp.setOperNumber(ZnDepotItem_temp.getOperNumber().add(znDepotItem.getOperNumber()));
                    map.put(znDepotItem.getMaterialId().toString(),ZnDepotItem_temp);
                }else{
                    map.put(znDepotItem.getMaterialId().toString(),znDepotItem);
                    materialIds.add(znDepotItem.getMaterialId());
                    materialIdSet.add(znDepotItem.getMaterialId());
                }
            }
            for (Map.Entry<String,ZnDepotItem> e:map.entrySet()) {
                znDepotItemList.add(e.getValue());
            }
            znMaterialCurrentStockMapper.updateMaterialStockNum(znDepotItemList,materialIds,znDepotHead.getTenantId(),updateType==0?1:0);
        }
        int updateCount2 = znDepotHeadMapper.deleteZnDepotItemByHeaderId(znDepotHead.getId());
        int updateCount3 =  insertZnDepotItem(znDepotHead);
        //2、有商品的出入库有商品库存变化，再更新商品库存
        if(updateType !=-1){
            Map<String,ZnDepotItem> map = new HashMap<>();
            List<ZnDepotItem> znDepotItemList = new ArrayList<>();
            Set<Long> materialIdSet = new HashSet<>();
            List<Long> materialIds = new ArrayList<>();
            for (ZnDepotItem znDepotItem:znDepotHead.getZnDepotItemList()) {
                if(materialIdSet.contains(znDepotItem.getMaterialId())){
                    ZnDepotItem ZnDepotItem_temp =  map.get(znDepotItem.getMaterialId().toString());
                    ZnDepotItem_temp.setBasicNumber(ZnDepotItem_temp.getBasicNumber().add(znDepotItem.getBasicNumber()));
//                    ZnDepotItem_temp.setOperNumber(ZnDepotItem_temp.getOperNumber().add(znDepotItem.getOperNumber()));
                    map.put(znDepotItem.getMaterialId().toString(),ZnDepotItem_temp);
                }else{
                    map.put(znDepotItem.getMaterialId().toString(),znDepotItem);
                    materialIds.add(znDepotItem.getMaterialId());
                    materialIdSet.add(znDepotItem.getMaterialId());
                }
            }
            for (Map.Entry<String,ZnDepotItem> e:map.entrySet()) {
                znDepotItemList.add(e.getValue());
            }
            znMaterialCurrentStockMapper.updateMaterialStockNum(znDepotItemList,materialIds,znDepotHead.getTenantId(),updateType);
        }
        ZnDepotHead ZnDepotHead = znDepotHeadMapper.selectZnDepotHeadById(znDepotHead.getId());
        if(znDepotHead.getType().equals("出库") && znDepotHead.getSubType().equals("零售") || znDepotHead.getType().equals("入库") && znDepotHead.getSubType().equals("零售退货")){
            if((!ZnDepotHead.getPayType().equals(znDepotHead.getPayType()) && BusinessConstants.PAY_TYPE_PREPAID.equals(znDepotHead.getPayType())) || (ZnDepotHead.getPayType().equals(znDepotHead.getPayType()) && !znDepotHead.getTotalPrice().equals(ZnDepotHead.getTotalPrice())) ){
                if(znDepotHead.getOrganId()!=null) {
                    ZnSupplier znSupplier = new ZnSupplier();
                    znSupplier.setType("会员");
                    znSupplier.setId(znDepotHead.getOrganId());
                    Map<String,Object> params = new HashMap<>();
                    params.put("advanceIn",znDepotHead.getTotalPrice().subtract(ZnDepotHead.getTotalPrice()));
                    params.put("updateType","-");

                    znSupplier.setParams(params);
                    znSupplierService.updateZnSupplier(znSupplier); //updateAdvanceIn(znDepotHead.getOrganId(), BigDecimal.ZERO.subtract(znDepotHead.getTotalPrice()));
                }
            }
        }
//        if(znDepotHead.getDiscountLastMoney()==null || znDepotHead.getDiscountLastMoney().doubleValue()==0){
//            znDepotHead.setDiscountLastMoney(znDepotHead.getTotalPrice());
//        }
//        if(znDepotHead.getChangeAmount()==null || znDepotHead.getChangeAmount().doubleValue()==0){
//            znDepotHead.setChangeAmount(znDepotHead.getDiscountLastMoney());
//        }
        //入库需要将金额转为负数
        if(BusinessConstants.DEPOTHEAD_TYPE_IN.equals(znDepotHead.getType())){
//            changeAmount backAmount totalPrice discountLastMoney
            znDepotHead.setChangeAmount(BigDecimal.ZERO.subtract(znDepotHead.getChangeAmount()));
            znDepotHead.setTotalPrice(BigDecimal.ZERO.subtract(znDepotHead.getTotalPrice()));
//            if(znDepotHead.getDiscountLastMoney() !=null){
//                znDepotHead.setDiscountLastMoney(BigDecimal.ZERO.subtract(znDepotHead.getDiscountLastMoney()));
//            }
        }
        int updateCount1 = znDepotHeadMapper.updateZnDepotHead(znDepotHead);
        int result = 1;
        if(!(updateCount1>0) && (updateCount2>0) && (updateCount3>0)){
            throw new ServiceException("修改单据异常");
        }
        return result;
    }

    /**
     * 批量删除单据管理
     *
     * @param ids 需要删除的单据管理主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteZnDepotHeadByIds(Long[] ids)
    {
        int result = 0;
        if(ids.length>0){
            //更新库存
            for (Long headId:ids) {
               ZnDepotHead znDepotHead = znDepotHeadMapper.selectZnDepotHeadById(headId);
                int updateType = -1;// -1 不操作 0 减库存  1加库存
                //删除商品的库存 出入库 刚好相反：入库 -   出库 +
                if(znDepotHead.getType().equals("入库")){
//                    if(!znDepotHead.getSubType().equals("其它")){
                        updateType = 0;
//                    }
                }else if(znDepotHead.getType().equals("出库")){
//                    if(!znDepotHead.getSubType().equals("其它")){
                        updateType = 1;
//                    }
                }
                if(updateType !=-1){
                    Map<String,ZnDepotItem> map = new HashMap<>();
                    List<ZnDepotItem> znDepotItemList = new ArrayList<>();
                    Set<Long> materialIdSet = new HashSet<>();
                    List<Long> materialIds = new ArrayList<>();
                    for (ZnDepotItem znDepotItem:znDepotHead.getZnDepotItemList()) {
                        if(materialIdSet.contains(znDepotItem.getMaterialId())){
                            ZnDepotItem ZnDepotItem_temp =  map.get(znDepotItem.getMaterialId().toString());
                            double d = ZnDepotItem_temp.getOperNumber().doubleValue() + znDepotItem.getOperNumber().doubleValue() * znDepotItem.getUnitRatio();
                            ZnDepotItem_temp.setOperNumber(new BigDecimal(d));
                            map.put(znDepotItem.getMaterialId().toString(),ZnDepotItem_temp);
                        }else{
                            map.put(znDepotItem.getMaterialId().toString(),znDepotItem);
                            materialIds.add(znDepotItem.getMaterialId());
                            materialIdSet.add(znDepotItem.getMaterialId());
                            ;                }
                    }
                    for (Map.Entry<String,ZnDepotItem> e:map.entrySet()) {
                        znDepotItemList.add(e.getValue());
                    }
                    znMaterialCurrentStockMapper.updateMaterialStockNum(znDepotItemList,materialIds,znDepotHead.getTenantId(),updateType);
                }
            }
            int delCount1 = znDepotHeadMapper.deleteZnDepotItemByHeaderIds(ids);
            //如果有关联订单，需要更新关联订单的状态
            int updateCount =znDepotHeadMapper.updateOrderStatusByIds(ids);
            int delCount2 = znDepotHeadMapper.deleteZnDepotHeadByIds(ids);
            if((delCount1>0) && (delCount2>0)){
                result = 1;
            }else{
                throw new ServiceException("订单删除异常");
            }
        }else{
            throw new ServiceException("请先选择删除订单");
        }

        return result;
    }

    /**
     * 删除单据管理信息
     *
     * @param id 单据管理主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteZnDepotHeadById(Long id)
    {
       int delCount1 = znDepotHeadMapper.deleteZnDepotItemByHeaderId(id);
        Long[] ids = {id};
        int updateCount =znDepotHeadMapper.updateOrderStatusByIds(ids);
        int delCount2 = znDepotHeadMapper.deleteZnDepotHeadById(id);
        int result = 1;
        if(!(delCount1>0) && (delCount2>0) && (updateCount>0)){
            throw new ServiceException("订单删除异常");
        }
        return result;
    }

    /**
     * 新增单据子信息
     *
     * @param znDepotHead 单据管理对象
     */
    public int insertZnDepotItem(ZnDepotHead znDepotHead)
    {
        if (znDepotHead.getOtherMoney() ==null){
            znDepotHead.setOtherMoney(BigDecimal.ZERO);
        }
        int result = 0;
        List<ZnDepotItem> znDepotItemList = znDepotHead.getZnDepotItemList();
        System.out.println(JSON.toJSONString(znDepotItemList));
        Long id = znDepotHead.getId();
        if (StringUtils.isNotNull(znDepotItemList))
        {
            List<ZnDepotItem> list = new ArrayList<ZnDepotItem>();
            BigDecimal total = BigDecimal.ZERO;
            for (ZnDepotItem znDepotItem : znDepotItemList)
            {
                znDepotItem.setHeaderId(id);
                znDepotItem.setTenantId(znDepotHead.getTenantId());
                znDepotItem.setDeleteFlag("0");
                znDepotItem.setAllPrice(znDepotItem.getOperNumber().multiply(znDepotItem.getUnitPrice()));
                if (znDepotItem.getTaxUnitPrice() ==null){
                    znDepotItem.setTaxUnitPrice(znDepotItem.getUnitPrice());
                }
                if (znDepotItem.getTaxRate() ==null){
                    znDepotItem.setTaxRate(new BigDecimal(0));
                }
                if(znDepotItem.getTaxMoney() ==null){
                    znDepotItem.setTaxMoney(new BigDecimal(0));
                }else{
                    znDepotItem.setTaxMoney(znDepotItem.getAllPrice().multiply(znDepotItem.getTaxRate()));
                }
                if(znDepotItem.getTaxLastMoney() ==null){
                    znDepotItem.setTaxLastMoney(znDepotItem.getAllPrice());
                }else{
                    //防止页面上计算价税合计 延迟，错误数据直接保存
                   if(znDepotItem.getTaxLastMoney().compareTo(znDepotItem.getTaxMoney().add(znDepotItem.getAllPrice())) !=0){
                       znDepotItem.setTaxLastMoney(znDepotItem.getTaxMoney().add(znDepotItem.getAllPrice()));
                   }
                }

                total = total.add(znDepotItem.getTaxLastMoney());
                System.out.println(JSON.toJSONString(znDepotItem));
                //单位数量统计转换、纠正
                   ZnMaterial material = znMaterialMapper.selectZnMaterialById(znDepotItem.getMaterialId());
                   if(material.getUnitId() !=null){
                        ZnUnit znUnit = znUnitMapper.selectZnUnitById(material.getUnitId());
                       if(znDepotItem.getMaterialUnit().equals(znUnit.getOtherUnit())){
                           znDepotItem.setBasicNumber(new BigDecimal(znUnit.getRatio()).multiply(znDepotItem.getOperNumber()));
                       }else if(znDepotItem.getMaterialUnit().equals(znUnit.getOtherUnitTwo())){
                           znDepotItem.setBasicNumber(new BigDecimal(znUnit.getRatioTwo()).multiply(znDepotItem.getOperNumber()));
                       }else if(znDepotItem.getMaterialUnit().equals(znUnit.getOtherUnitThree())){
                           znDepotItem.setBasicNumber(new BigDecimal(znUnit.getRatioThree()).multiply(znDepotItem.getOperNumber()));
                       }else{
                           znDepotItem.setBasicNumber(znDepotItem.getOperNumber());
                       }
                   }else{
                       znDepotItem.setBasicNumber(znDepotItem.getOperNumber());
                   }

                list.add(znDepotItem);

                //如果是采购单，更新商品的采购价
                if(znDepotHead.getType().equals("入库") && znDepotHead.getSubType().equals("采购")){
                    ZnMaterialExtend znMaterialExtend = new ZnMaterialExtend();
                    znMaterialExtend.setMaterialId(znDepotItem.getMaterialId());
                    znMaterialExtend.setTenantId(SecurityUtils.getTenantId());
                    znMaterialExtend.setId(znDepotItem.getMaterialExtendId());
//                    znMaterialExtend.setPurchaseDecimal(znDepotItem.getUnitPrice());
//                    znMaterialExtend.setBarCode(znDepotItem.getBarCode());
                    Map<String,Object> map = znMaterialMapper.selectMaterialStockNumberAndPurchaseDecimal(znMaterialExtend);
                    if(!map.isEmpty()){
                        BigDecimal totalCurrentNumber = new BigDecimal(map.get("total_current_number").toString()) ;
                        BigDecimal maxPurchaseDecimal = new BigDecimal(map.get("max_purchase_decimal").toString()) ;
                        BigDecimal newPurchaseDecimal = BigDecimal.ZERO;
                        if(totalCurrentNumber.doubleValue()==0){
                            newPurchaseDecimal = znDepotItem.getUnitPrice();
                        }else{
                             newPurchaseDecimal =  maxPurchaseDecimal.max(znDepotItem.getUnitPrice());
                        }
                        znMaterialExtend.setPurchaseDecimal(newPurchaseDecimal);
                       int updateCount = znMaterialMapper.updateZnMaterialPurchaseDecimal(znMaterialExtend);
                    }
                }
            }
            //当订单的总金额 <> 单据产品价格之和 ，更新单据单据金额和优惠后金额、优惠后金额
            if(znDepotHead.getTotalPrice().compareTo(total)!=0 && total.compareTo(BigDecimal.ZERO)>0){
                znDepotHead.setTotalPrice(total);
                if(znDepotHead.getDiscount()==null && znDepotHead.getDiscountMoney()!=null && znDepotHead.getDiscountMoney().compareTo(BigDecimal.ZERO)>0){
                    znDepotHead.setDiscount(znDepotHead.getDiscountMoney().divide(total.multiply(new BigDecimal(100)),4,BigDecimal.ROUND_HALF_UP));
                }
                znDepotHead.setDiscountLastMoney(znDepotHead.getTotalPrice().subtract(znDepotHead.getDiscountMoney()!=null && znDepotHead.getDiscountMoney().compareTo(BigDecimal.ZERO)>0?znDepotHead.getDiscountMoney():BigDecimal.ZERO).subtract(znDepotHead.getOtherMoney() !=null && znDepotHead.getOtherMoney().compareTo(BigDecimal.ZERO)>0?znDepotHead.getOtherMoney():BigDecimal.ZERO));
                znDepotHeadMapper.updateZnDepotHead(znDepotHead);
            }
            if (list.size() > 0)
            {
                result =  znDepotHeadMapper.batchZnDepotItem(list);
            }
        }
        return result;
    }
    /**
     * 获取单据编号
     * @param  type 1 零售(0出库[LSCK]、1退货[LSTH]) 2销售（0订单[SSDD] 1出库[SSCK] 2退货[SSTH]） 3 采购（0订单[CGDD] 1出库[CGCK] 2退货[CGTH]） 5其它（0入库[QTRK] 1出库[QTCK] 2调拨出库[DBCK] 3组装单[ZZDD] 4拆卸单[CXDD]） 为文字拼音的首字母
     */
    @Override
    public String getBillNo(String type) {
        Long buildOnlyNumber=null;
        String result = "";
        synchronized (this){
            String key =  RedisConstant.BILL_NO  +"_" + type;
            Long retailNo = redisCache.getCacheObject(key);
            if(retailNo ==null){
                buildOnlyNumber = 1l;
            }else{
                buildOnlyNumber = retailNo;
            }
            redisCache.setCacheObject(key,buildOnlyNumber+1);

            if(buildOnlyNumber< Constants.SEQ_TO_STRING_MIN_LENGTH){
                StringBuffer sb=new StringBuffer(buildOnlyNumber.toString());
                int len=Constants.SEQ_TO_STRING_MIN_LENGTH.toString().length()-sb.length();
                for(int i=0;i<len;i++){
                    sb.insert(0,Constants.SEQ_TO_STRING_LESS_INSERT);
                }
                result =  type + sb.toString();
            }else{
                result =  type + buildOnlyNumber.toString();
            }
            if(redisCache.getCacheSet(RedisConstant.USED_BILL_NO + "_"  + SecurityUtils.getTenantId() +"_" + type).contains(result)){
                getBillNo(type);
            }
        }
        return result;
    }

    @Override
    public int changeStatus(Long[] ids, String status) {
        return znDepotHeadMapper.changeStatus(ids,status);
    }

    @Override
    public List<DepotItemVo4WithInfoEx> selectZnDepotHeadPage(String orderType,String materialParam, String startTime, String endTime) {
        Long tenantId=SecurityUtils.getTenantId();
        return znDepotHeadMapper.selectZnDepotHeadPage(orderType, materialParam,startTime,endTime,tenantId);
    }

    @Override
    public BigDecimal buyOrSale(String type, String subType, Long mId, Long materialExtendId, String monthTime, String sumType) {
        BigDecimal result= BigDecimal.ZERO;
        try{
            String beginTime = DateUtils.firstDayOfMonth(monthTime) + DateUtils.DAY_FIRST_TIME;
            String endTime = DateUtils.lastDayOfMonth(monthTime) + DateUtils.DAY_LAST_TIME;
            Long tenantId=SecurityUtils.getTenantId();
            if (SUM_TYPE.equals(sumType)) {
                result= znDepotHeadMapper.buyOrSaleNumber(type, subType, mId,  beginTime, endTime, sumType,tenantId);
            } else {
                result= znDepotHeadMapper.buyOrSalePrice(type, subType, mId,  beginTime, endTime, sumType,tenantId);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public List<DepotHeadVo4InDetail> findByAll(String beginTime, String endTime, String type, String materialParam, List<Long> depotList, Long oId, String number,String status) {
        List<DepotHeadVo4InDetail> list = null;
        Long tenantId=SecurityUtils.getTenantId();
            list =znDepotHeadMapper.findByAll(beginTime, endTime, type, materialParam, depotList, oId, number,status,tenantId);

        return list;
    }

    @Override
    public List<DepotHeadVo4InDetail> findAllocationDetail(String beginTime, String endTime, String subType, String number, String materialParam, List<Long> depotList, List<Long> depotFList) {
        List<DepotHeadVo4InDetail> list = null;
        Long tenantId=SecurityUtils.getTenantId();
            list =znDepotHeadMapper.findAllocationDetail(beginTime, endTime, subType, number, materialParam, depotList, depotFList,tenantId);

        return list;
    }

    @Override
    public List<DepotHeadVo4InOutMCount> findInOutMaterialCount(String beginTime, String endTime, String type, String materialParam, List<Long> depotList, Long oId) {
        List<DepotHeadVo4InOutMCount> list = null;
        Long tenantId=SecurityUtils.getTenantId();
            list =znDepotHeadMapper.findInOutMaterialCount(beginTime, endTime, type, materialParam, depotList, oId,tenantId);

        return list;
    }

    @Override
    public List<DepotItemVo4WithInfoEx> findInOutStockReport(String materialParam, String endTime) {
        List<DepotItemVo4WithInfoEx> list =null;
        Long tenantId=SecurityUtils.getTenantId();
            list = znDepotHeadMapper.findInOutStockReport(materialParam, endTime,tenantId);

        return list;
    }

    /**
     * 库存统计-多仓库
     * @param depotList
     * @param mId
     * @param beginTime
     * @param endTime
     * @return
     */
    @Override
    public BigDecimal getStockByParamWithDepotList(List<Long> depotList, Long mId, String beginTime, String endTime){
        //初始库存
        BigDecimal initStock = znMaterialInitialStockService.getInitStockByMidAndDepotList(depotList, mId);
        //盘点复盘后数量的变动
        BigDecimal stockCheckSum = znDepotHeadMapper.getStockCheckSumByDepotList(depotList, mId, beginTime, endTime);
        DepotItemVo4Stock stockObj = znDepotHeadMapper.getStockByParamWithDepotList(depotList, mId, beginTime, endTime);
        BigDecimal stockSum = BigDecimal.ZERO;
        if(stockObj!=null) {
            BigDecimal inTotal = stockObj.getInTotal();
            BigDecimal transfInTotal = stockObj.getTransfInTotal();
            BigDecimal assemInTotal = stockObj.getAssemInTotal();
            BigDecimal disAssemInTotal = stockObj.getDisAssemInTotal();
            BigDecimal outTotal = stockObj.getOutTotal();
            BigDecimal transfOutTotal = stockObj.getTransfOutTotal();
            BigDecimal assemOutTotal = stockObj.getAssemOutTotal();
            BigDecimal disAssemOutTotal = stockObj.getDisAssemOutTotal();
            stockSum = inTotal.add(transfInTotal).add(assemInTotal).add(disAssemInTotal)
                    .subtract(outTotal).subtract(transfOutTotal).subtract(assemOutTotal).subtract(disAssemOutTotal);
        }
        return initStock.add(stockCheckSum).add(stockSum);
    }
    /**
     * 统计时间段内的入库和出库数量-多仓库
     * @param depotList
     * @param mId
     * @param beginTime
     * @param endTime
     * @return
     */
    @Override
    public Map<String, BigDecimal> getIntervalMapByParamWithDepotList(List<Long> depotList, Long mId, String beginTime, String endTime) {
        Map<String,BigDecimal> intervalMap = new HashMap<>();
        BigDecimal inSum = BigDecimal.ZERO;
        BigDecimal outSum = BigDecimal.ZERO;
        //盘点复盘后数量的变动
        BigDecimal stockCheckSum = znDepotHeadMapper.getStockCheckSumByDepotList(depotList, mId, beginTime, endTime);
        DepotItemVo4Stock stockObj = znDepotHeadMapper.getStockByParamWithDepotList(depotList, mId, beginTime, endTime);
        if(stockObj!=null) {
            BigDecimal inTotal = stockObj.getInTotal();
            BigDecimal transfInTotal = stockObj.getTransfInTotal();
            BigDecimal assemInTotal = stockObj.getAssemInTotal();
            BigDecimal disAssemInTotal = stockObj.getDisAssemInTotal();
            inSum = inTotal.add(transfInTotal).add(assemInTotal).add(disAssemInTotal);
            BigDecimal outTotal = stockObj.getOutTotal();
            BigDecimal transfOutTotal = stockObj.getTransfOutTotal();
            BigDecimal assemOutTotal = stockObj.getAssemOutTotal();
            BigDecimal disAssemOutTotal = stockObj.getDisAssemOutTotal();
            outSum = outTotal.add(transfOutTotal).add(assemOutTotal).add(disAssemOutTotal);
        }
        if(stockCheckSum.compareTo(BigDecimal.ZERO)>0) {
            inSum = inSum.add(stockCheckSum);
        } else {
            //盘点复盘数量为负数代表出库
            outSum = outSum.subtract(stockCheckSum);
        }
        intervalMap.put("inSum", inSum);
        intervalMap.put("outSum", outSum);
        return intervalMap;
    }

    @Override
    public List<DepotHeadVo4StatementAccount> findStatementAccount(String beginTime, String endTime, Long organId, String supType) {
        List<DepotHeadVo4StatementAccount> list = null;
            int j = 1;
            if (supType.equals("客户")) { //客户
                j = 1;
            } else if (supType.equals("供应商")) { //供应商
                j = -1;
            }
            Long tenantId=SecurityUtils.getTenantId();
            list =znDepotHeadMapper.findStatementAccount(beginTime, endTime, organId, supType,tenantId);
            if (null != list) {
                for (DepotHeadVo4StatementAccount dha : list) {
                    dha.setNumber(dha.getNumber()); //单据编号
                    dha.setType(dha.getType()); //类型
                    String type = dha.getType();
                    BigDecimal p1 = BigDecimal.ZERO ;
                    BigDecimal p2 = BigDecimal.ZERO;
                    if (dha.getDiscountLastMoney() != null) {
                        p1 = dha.getDiscountLastMoney();
                    }
                    if (dha.getChangeAmount() != null) {
                        p2 = dha.getChangeAmount();
                    }
                    BigDecimal allPrice = BigDecimal.ZERO;
                    if ((p1.compareTo(BigDecimal.ZERO))==-1) {
                        p1 = p1.abs();
                    }
                    if(dha.getOtherMoney()!=null) {
                        p1 = p1.add(dha.getOtherMoney()); //与其它费用相加
                    }
                    if ((p2 .compareTo(BigDecimal.ZERO))==-1) {
                        p2 = p2.abs();
                    }
                    if (type.equals("采购入库")) {
                        allPrice = p2.subtract(p1);
                    } else if (type.equals("销售退货入库")) {
                        allPrice = p2.subtract(p1);
                    } else if (type.equals("销售出库")) {
                        allPrice = p1.subtract(p2);
                    } else if (type.equals("采购退货出库")) {
                        allPrice = p1.subtract(p2);
                    } else if (type.equals("收款")) {
                        allPrice = BigDecimal.ZERO.subtract(p1);
                    } else if (type.equals("付款")) {
                        allPrice = p1;
                    } else if (type.equals("收入")) {
                        allPrice =  p1.subtract(p2);
                    } else if (type.equals("支出")) {
                        allPrice = p2.subtract(p1);
                    }
                    dha.setBillMoney(p1); //单据金额
                    dha.setChangeAmount(p2); //实际支付
                    DecimalFormat df = new DecimalFormat(".##");
                    dha.setAllPrice(new BigDecimal(df.format(allPrice.multiply(new BigDecimal(j))))); //本期变化
                    dha.setSupplierName(dha.getSupplierName()); //单位名称
                    dha.setoTime(dha.getoTime()); //单据日期
                }
            }

        return list;
    }

    @Override
    public BigDecimal findTotalPay(Long supplierId, String endTime, String supType) {
        BigDecimal sum = BigDecimal.ZERO;
        String getS = supplierId.toString();
        if (("客户").equals(supType)) { //客户
            sum = allMoney(getS, "出库", "销售", "合计",endTime).subtract(allMoney(getS, "出库", "销售", "实际",endTime));
        } else if (("供应商").equals(supType)) { //供应商
            sum = allMoney(getS, "入库", "采购", "合计",endTime).subtract(allMoney(getS, "入库", "采购", "实际",endTime));
        }
        return sum;
    }

    @Override
    public BigDecimal allMoney(String getS, String type, String subType, String mode, String endTime) {
        BigDecimal allMoney = BigDecimal.ZERO;
        try {
            Long supplierId = Long.valueOf(getS);
            BigDecimal sum = findAllMoney(supplierId, type, subType, mode, endTime);
            if(sum != null) {
                allMoney = sum;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //返回正数，如果负数也转为正数
        if ((allMoney.compareTo(BigDecimal.ZERO))==-1) {
            allMoney = allMoney.abs();
        }
        return allMoney;
    }



    @Override
    public BigDecimal findAllMoney(Long supplierId, String type, String subType, String mode, String endTime) {
        String modeName = "";
        BigDecimal allOtherMoney = BigDecimal.ZERO;
        if (mode.equals("实际")) {
            modeName = "change_amount";
        } else if (mode.equals("合计")) {
            modeName = "discount_last_money";
            allOtherMoney = znDepotHeadMapper.findAllOtherMoney(supplierId, type, subType, endTime);
        }
        BigDecimal result = BigDecimal.ZERO;
            result =znDepotHeadMapper.findAllMoney(supplierId, type, subType, modeName, endTime);

        if(allOtherMoney!=null) {
            result = result.add(allOtherMoney);
        }
        return result;
    }

    @Override
    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public List<DepotItemStockWarningCount> findStockWarningCount(String materialParam, List<Long> depotList) {
        List<DepotItemStockWarningCount> list = null;
            list =znDepotHeadMapper.findStockWarningCount(materialParam, depotList);

        return list;
    }

    @Override
    public List<DepotItemVo4DetailByTypeAndMId> findDetailByTypeAndMaterialIdList(Map<String, String> parameterMap) {
        String mIdStr = parameterMap.get("mId");
        String billNo = parameterMap.get("billNo");
        String type = parameterMap.get("type");
        String subType = parameterMap.get("subType");
        String beginOperTime = parameterMap.get("beginOperTime");
        String endOperTime = parameterMap.get("endOperTime");
        Long mId = null;
        if(!StringUtil.isEmpty(mIdStr)) {
            mId = Long.parseLong(mIdStr);
        }
        List<DepotItemVo4DetailByTypeAndMId> list =null;
            list = znDepotHeadMapper.findDetailByTypeAndMaterialIdList(mId,billNo,type,subType,beginOperTime,endOperTime,SecurityUtils.getTenantId());

        return list;
    }

    @Override
    public List<ZnDepotItem> selectZnDepotItemByHeadId(Long id) {
        ZnDepotItem znDepotItem = new ZnDepotItem();
        znDepotItem.setHeaderId(id);
        znDepotItem.setTenantId(SecurityUtils.getTenantId());
        return znDepotHeadMapper.selectZnDepotItemList(znDepotItem);
    }

    public List<DepotHeadVo4List> getDetailByNumber(String number) throws Exception {
        List<DepotHeadVo4List> resList = new ArrayList<DepotHeadVo4List>();
        List<DepotHeadVo4List> list = null;
            Map<Long,String> personMap = znPersonService.getPersonMap();
            Map<Long,String> accountMap = znAccountService.getAccountMap();
            Long tenantId=SecurityUtils.getTenantId();
            list = znDepotHeadMapper.getDetailByNumber(number,tenantId);
            if (null != list) {
                for (DepotHeadVo4List dh : list) {
                    if(accountMap!=null && StringUtil.isNotEmpty(dh.getAccountIdList()) && StringUtil.isNotEmpty(dh.getAccountMoneyList())) {
                        String accountStr = znAccountService.getAccountStrByIdAndMoney(accountMap, dh.getAccountIdList(), dh.getAccountMoneyList());
                        dh.setAccountName(accountStr);
                    }
                    if(dh.getAccountIdList() != null) {
                        String accountidlistStr = dh.getAccountIdList().replace("[", "").replace("]", "").replaceAll("\"", "");
                        dh.setAccountIdList(accountidlistStr);
                    }
                    if(dh.getAccountMoneyList() != null) {
                        String accountmoneylistStr = dh.getAccountMoneyList().replace("[", "").replace("]", "").replaceAll("\"", "");
                        dh.setAccountMoneyList(accountmoneylistStr);
                    }
                    if(dh.getChangeAmount() != null) {
                        dh.setChangeAmount(dh.getChangeAmount().abs());
                    }
                    if(dh.getTotalPrice() != null) {
                        dh.setTotalPrice(dh.getTotalPrice().abs());
                    }
                    if(StringUtil.isNotEmpty(dh.getSalesMan())) {
                        dh.setSalesManStr(znPersonService.getPersonByMapAndIds(personMap,dh.getSalesMan()));
                    }
                    dh.setOperTimeStr(DateUtils.getCenternTime(dh.getOperTime()));
                    dh.setMaterialsList(findMaterialsListByHeaderId(dh.getId()));
                    dh.setCreatorName(SecurityUtils.getUsername());
                    resList.add(dh);
                }
            }

        return resList;
    }

    @Override
    public List<DepotItemVo4WithInfoEx> getDetailList(Long headerId) {
        return znDepotHeadMapper.getDetailList(headerId);
    }



    /**
     * 库存统计-单仓库
     * @param depotId
     * @param mId
     * @param beginTime
     * @param endTime
     * @return
     */
    @Override
    public BigDecimal getStockByParam(Long depotId, Long mId, String beginTime, String endTime){
        List<Long> depotList = new ArrayList<>();
        if(depotId != null) {
            depotList.add(depotId);
        }
        return getStockByParamWithDepotList(depotList, mId, beginTime, endTime);
    }

    @Override
    @Transactional(value = "transactionManager", rollbackFor = Exception.class)
    public BigDecimal getFinishNumber(Long mId, Long headerId) {
        String goToType = "";
        ZnDepotHead depotHead =znDepotHeadMapper.selectZnDepotHeadById(headerId);
        String linkNumber = depotHead.getNumber(); //订单号
        if(Constants.SUB_TYPE_PURCHASE_ORDER.equals(depotHead.getSubType())) {
            goToType = Constants.SUB_TYPE_PURCHASE;
        }
        if(Constants.SUB_TYPE_SALES_ORDER.equals(depotHead.getSubType())) {
            goToType = Constants.SUB_TYPE_SALES;
        }
        BigDecimal count = znDepotHeadMapper.getFinishNumber(mId, linkNumber, goToType);
        return count;
    }

    @Override
    @Transactional
    public List<ZnDepotHead> selectZnDepotHeadDebtList(ZnDepotHead znDepotHead) {
        znDepotHead.setTenantId(SecurityUtils.getTenantId());
        if(StringUtils.isNotBlank(znDepotHead.getMaterial())){
            znDepotHead.setMaterial(znDepotHead.getMaterial().trim());
        }
        ZnCompanyConfig znCompanyConfig= redisCache.getCacheObject(RedisConstant.SYSTEM_CONFIG+"_"+SecurityUtils.getTenantId());
        if(znCompanyConfig!=null){
            boolean depotFlag ="1".equals(znCompanyConfig.getDepotFlag())?true:false; //获取系统配置，是否需要用户需要分配仓库，暂时先写false
            if(depotFlag) {
                List<String> depotIds = redisCache.getCacheList(RedisConstant.SYSTEM_CONFIG_USER_DEPOT_LIST +"_"+SecurityUtils.getTenantId());
                List<Long> values=new ArrayList<>();
                if(null!=depotIds&&depotIds.size()>0){
                    Map<String,Object> params = new HashMap<>();
                    params.put("depotIds",depotIds);
                    znDepotHead.setParams(params);
                }
            }
        }
        znDepotHead.getParams().put("isDebt",1);
//        znDepotHead.setType(null);
        znDepotHead.setSubType(null);
        List<ZnDepotHead> list = znDepotHeadMapper.selectZnDepotHeadList(znDepotHead);
        if (list.size()>0){
            for (ZnDepotHead depotHead:list) {
                String materialNames = znDepotHeadMapper.findMaterialsListByHeaderId(depotHead.getId());
                depotHead.setMaterial(materialNames);
//                ZnAccountItem znAccountItem = new ZnAccountItem();
//                znAccountItem.setBillId(depotHead.getId());
//                znAccountItem.setTenantId(SecurityUtils.getTenantId());
//                BigDecimal inOrOutDebtMoney = znAccountItemMapper.selectInOrOutDebtMoney(znAccountItem);
//                System.out.println(inOrOutDebtMoney);
//                depotHead.setReceivedDebtMoney(inOrOutDebtMoney);
            }
        }
        return list;
    }

    /**
     * 查询订单商品列表，仅有导出字段
     * @param id
     * @return
     */
    @Override
    public List<ZnDepotItemExportTemplate> selectExportZnDepotItemByHeadId(Long id) {
        return znDepotHeadMapper.selectExportZnDepotItemByHeadId(id);
    }

    @Override
    public List<ZnDepotItemExportTemplate> selectExportZnDepotItemByHeadIds(List<Long> headIds) {
        return znDepotHeadMapper.selectExportZnDepotItemByHeadIds(headIds);
    }

    @Override
    public void exportOrder(HttpServletResponse response,ZnDepotHead znDepotHead) {
        String exportType = "0";// 0 导出明细  1导出汇总
        if(znDepotHead.getParams().containsKey("exportType")){
            exportType = znDepotHead.getParams().get("exportType").toString();
        }
        String[] ids = znDepotHead.getParams().get("ids").toString().split(",");
        String[] billNos = znDepotHead.getParams().get("billNos").toString().split(",");
        Map<String,List<ZnDepotItemExportTemplate>> map = new HashMap<>();
        if(exportType.equals("0")){
            int i=0;
            for (String id:ids) {
                List<ZnDepotItemExportTemplate> list = znDepotHeadMapper.selectExportZnDepotItemByHeadId(Long.valueOf(id));
                map.put(billNos[i],list);
                i++;
            }
            ExcelUtil<ZnDepotItemExportTemplate> util = new ExcelUtil<ZnDepotItemExportTemplate>(ZnDepotItemExportTemplate.class);
            util.exportExcelMulSheet(response, map , null);
        }else{
            List<Long> headIds = Arrays.stream(ids)
                    .map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
            List<ZnDepotItemExportTemplate> list = znDepotHeadMapper.selectExportZnDepotItemByHeadIds(headIds);
            List<DepotItemAllVoEx> result = new ArrayList<>();
            for (ZnDepotItemExportTemplate ex:list) {
                DepotItemAllVoEx vo = new DepotItemAllVoEx();
                BeanUtils.copyProperties(ex,vo);
                result.add(vo);
            }
            ExcelUtil<DepotItemAllVoEx> util = new ExcelUtil<DepotItemAllVoEx>(DepotItemAllVoEx.class);
            util.exportExcel(response, result , "订单商品汇总");
        }
    }

    /**
     * 库存统计-sku
     * @param depotId
     * @param meId
     * @param beginTime
     * @param endTime
     * @return
     */
    @Override
    public BigDecimal getSkuStockByParam(Long depotId, Long meId, String beginTime, String endTime){
        DepotItemVo4Stock stockObj = znDepotHeadMapper.getSkuStockByParam(depotId, meId, beginTime, endTime);
        BigDecimal stockSum = BigDecimal.ZERO;
        if(stockObj!=null) {
            BigDecimal inTotal = stockObj.getInTotal();
            BigDecimal transfInTotal = stockObj.getTransfInTotal();
            BigDecimal assemInTotal = stockObj.getAssemInTotal();
            BigDecimal disAssemInTotal = stockObj.getDisAssemInTotal();
            BigDecimal outTotal = stockObj.getOutTotal();
            BigDecimal transfOutTotal = stockObj.getTransfOutTotal();
            BigDecimal assemOutTotal = stockObj.getAssemOutTotal();
            BigDecimal disAssemOutTotal = stockObj.getDisAssemOutTotal();
            stockSum = inTotal.add(transfInTotal).add(assemInTotal).add(disAssemInTotal)
                    .subtract(outTotal).subtract(transfOutTotal).subtract(assemOutTotal).subtract(disAssemOutTotal);
        }
        return stockSum;
    }

    private String findMaterialsListByHeaderId(Long id) {
        String result = null;
            result = znDepotHeadMapper.findMaterialsListByHeaderId(id);

        return result;
    }

    @Override
    public Map<String,Object> selectReport(int type) {

        return znDepotHeadMapper.selectReport(type,SecurityUtils.getTenantId());
    }

    @Override
    public List<Map<String, Object>> selectLastSixMonthReport() {
        return znDepotHeadMapper.selectLastSixMonthReport(SecurityUtils.getTenantId());
    }
    /**
     * 利润统计计算(先进先出），只计算采购和销售
     * 截止到目前为止，按自然月进行逐月进行统计，并且统计月份内的销售出库都必须是已出库状态。
     * @return
     */

    public static void main(String[] args) {
        String computeTime = "2022-08";
        Calendar cal = Calendar.getInstance();
        cal.set(Integer.parseInt(computeTime.split("-")[0]),Integer.parseInt(computeTime.split("-")[1])-1,1);
        System.out.println(cal.get(Calendar.MONTH));
        System.out.println(cal.getActualMaximum(Calendar.DATE));
    }
    public int selectZnDepotHeadCount(ZnDepotHead znDepotHead){
        return znDepotHeadMapper.selectZnDepotHeadCount(znDepotHead);

    }
    /**
     * 定时任务 - 按照每天进行一次库存查询比对，不正确的记录下来
     */
    @Override
    public void stockTask() {
        List<Map<String,List<String>>> errList = new ArrayList<>();
        List<String> errMaterialList = new ArrayList<>();
        Map<String,List<String>> errMap = new HashMap<>();//key 租户ID_仓库ID_商品ID_商品名称
        try {
            List<Map<String,Object>> list = znMaterialMapper.selectZnmaterialStock();
            for (Map<String,Object> map:list) {
                Long tenantId = Long.valueOf(map.get("tenant_id").toString());
                Long materialId = Long.valueOf(map.get("id").toString());
                String materialName = map.get("name").toString();
                Long depotId = null;
                String mapKey =  materialId + "_" + materialName;
                if(!map.containsKey("depot_id")){
                    errMaterialList.add("没有仓库ID");
                }else {
                    depotId = Long.valueOf(map.get("depot_id").toString());
                    mapKey = depotId + "_" + materialId + "_" + materialName;
                    errMaterialList = new ArrayList<>();
                    if (!map.containsKey("current_number") || !map.containsKey("init_number")) {
                        if (!map.containsKey("current_number")) {
                            errMaterialList.add("没有库存记录");
                        }
//                        //商品新增的时候，只有有初始库存才记录，不做判断
//                        if(!map.containsKey("init_number")){
//                            errMaterialList.add("没有初始库存记录");
//                        }
                    } else {
                        BigDecimal currentNumber = new BigDecimal(map.get("current_number").toString());
                        BigDecimal initNumber = map.containsKey("init_number") ? new BigDecimal(map.get("init_number").toString()) : BigDecimal.ZERO;
                        ZnDepotItem znDepotItem = new ZnDepotItem();
                        znDepotItem.setMaterialId(materialId);
                        znDepotItem.setDepotId(depotId);
                        znDepotItem.setTenantId(tenantId);
                        List<Map<String, Object>> resultList = znDepotHeadMapper.selectMaterialInOutTotal(znDepotItem);
                        if (resultList != null && resultList.size() > 0 ) {
                            BigDecimal totalNumber = new BigDecimal(resultList.get(0).get("total_number").toString());
                            BigDecimal inNumber = new BigDecimal(resultList.get(0).get("in_number").toString());
                            BigDecimal outNumber = new BigDecimal(resultList.get(0).get("out_number").toString());
                            if (!currentNumber.equals(totalNumber.add(initNumber))) {//当前库存 = 单据进出总和+初始库存
                                errMaterialList.add("库存数量不正确【初始库存：" + initNumber + ";库存：" + currentNumber + ";单据总数量：" + totalNumber + ";单据入库数量：" + inNumber + ";单据出库数量：" + outNumber + "】");
                            }
                        } else {
                            if (!currentNumber.equals(initNumber)) {
                                String temp = "无出入库单据，且库存数量不正确【初始库存：" + initNumber + ";库存：" + currentNumber + ";】";
                                errMaterialList.add(temp);
                            }
                        }
                    }
                }
                if(!errMaterialList.isEmpty()){
                    errMap = new HashMap<>();
                    errMap.put(mapKey,errMaterialList);
                    errList.add(errMap);
                }
            }
        }catch (Exception e){
            errMaterialList = new ArrayList<>();
            errMap = new HashMap<>();
            errMaterialList.add(e.getMessage());
            errMap.put("程序异常",errMaterialList);
            errList.add(errMap);
            e.printStackTrace();
        }finally {
            ZnStockCheckHistory znStockCheckHistory = new ZnStockCheckHistory();
            znStockCheckHistory.setType(0);
            znStockCheckHistory.setCreateTime(new Date());
            if (errList.isEmpty()){
                znStockCheckHistory.setState(1);
                znStockCheckHistory.setResult("无异常");
            }else{
                znStockCheckHistory.setResult(JSON.toJSONString(errList));
            }
            znStockCheckHistoryMapper.insertZnStockCheckHistory(znStockCheckHistory);
        }
    }
    /**
     * 定时任务 - 按照每天进行一次单据查询比对，异常的记录下来
     */
    @Override
    public void billTask() {
        List<Map<String,String>> errList = new ArrayList<>();
        Map<String,String> errMap = new HashMap<>();//key 租户ID_单据编号_商品ID_商品名称
        try {
            List<Map<String, Object>> list = znDepotHeadMapper.selectZnDepotItemErrorList();
            String mapKey = "";
            for (Map<String,Object> map:list) {
                mapKey = map.get("tenant_id").toString()+"_" + map.get("bill_no").toString()+"_" + map.get("material_id").toString()+"_" + map.get("material_name").toString();
                errMap = new HashMap<>();
                errMap.put(mapKey,JSON.toJSONString(map));
                errList.add(errMap);
            }
        }catch (Exception e){
            errMap = new HashMap<>();
            errMap.put("程序异常",e.getMessage());
            errList.add(errMap);
            e.printStackTrace();
        }finally {
            ZnStockCheckHistory znStockCheckHistory = new ZnStockCheckHistory();
            znStockCheckHistory.setType(1);
            znStockCheckHistory.setCreateTime(new Date());
            if (errList.isEmpty()){
                znStockCheckHistory.setState(1);
                znStockCheckHistory.setResult("无异常");
            }else{
                znStockCheckHistory.setResult(JSON.toJSONString(errList));
            }
            znStockCheckHistoryMapper.insertZnStockCheckHistory(znStockCheckHistory);
        }
    }
}
